home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 1: Comms & Networking / Almathera Ten on Ten - Disc 1: Comms & Networking.iso / amiga-useful / perl / src / cons.c < prev    next >
C/C++ Source or Header  |  1995-05-04  |  36KB  |  1,443 lines

  1. /* $RCSfile: cons.c,v $$Revision: 4.0.1.3 $$Date: 92/06/08 12:18:35 $
  2.  *
  3.  *    Copyright (c) 1991, Larry Wall
  4.  *
  5.  *    You may distribute under the terms of either the GNU General Public
  6.  *    License or the Artistic License, as specified in the README file.
  7.  *
  8.  * $Log:    cons.c,v $
  9.  * Revision 4.0.1.3  92/06/08  12:18:35  lwall
  10.  * patch20: removed implicit int declarations on funcions
  11.  * patch20: deleted some minor memory leaks
  12.  * patch20: fixed double debug break in foreach with implicit array assignment
  13.  * patch20: fixed confusion between a *var's real name and its effective name
  14.  * patch20: Perl now distinguishes overlapped copies from non-overlapped
  15.  * patch20: debugger sometimes displayed wrong source line
  16.  * patch20: various error messages have been clarified
  17.  * patch20: an eval block containing a null block or statement could dump core
  18.  * 
  19.  * Revision 4.0.1.2  91/11/05  16:15:13  lwall
  20.  * patch11: debugger got confused over nested subroutine definitions
  21.  * patch11: prepared for ctype implementations that don't define isascii()
  22.  * 
  23.  * Revision 4.0.1.1  91/06/07  10:31:15  lwall
  24.  * patch4: new copyright notice
  25.  * patch4: added global modifier for pattern matches
  26.  * 
  27.  * Revision 4.0  91/03/20  01:05:51  lwall
  28.  * 4.0 baseline.
  29.  * 
  30.  */
  31.  
  32. #include "EXTERN.h"
  33. #include "perl.h"
  34. #include "perly.h"
  35.  
  36. extern char *tokename[];
  37. extern int yychar;
  38.  
  39. static int cmd_tosave();
  40. static int arg_tosave();
  41. static int spat_tosave();
  42. static void make_cswitch();
  43. static void make_nswitch();
  44.  
  45. static bool saw_return;
  46.  
  47. SUBR *
  48. make_sub(name,cmd)
  49. char *name;
  50. CMD *cmd;
  51. {
  52.     register SUBR *sub;
  53.     STAB *stab = stabent(name,TRUE);
  54.  
  55.     if (sub = stab_sub(stab)) {
  56.     if (dowarn) {
  57.         CMD *oldcurcmd = curcmd;
  58.  
  59.         if (cmd)
  60.         curcmd = cmd;
  61.         warn("Subroutine %s redefined",name);
  62.         curcmd = oldcurcmd;
  63.     }
  64.     if (!sub->usersub && sub->cmd) {
  65.         cmd_free(sub->cmd);
  66.         sub->cmd = Nullcmd;
  67.         afree(sub->tosave);
  68.     }
  69.     Safefree(sub);
  70.     }
  71.     Newz(101,sub,1,SUBR);
  72.     stab_sub(stab) = sub;
  73.     sub->filestab = curcmd->c_filestab;
  74.     saw_return = FALSE;
  75.     tosave = anew(Nullstab);
  76.     tosave->ary_fill = 0;    /* make 1 based */
  77.     (void)cmd_tosave(cmd,FALSE);    /* this builds the tosave array */
  78.     sub->tosave = tosave;
  79.     if (saw_return) {
  80.     struct compcmd mycompblock;
  81.  
  82.     mycompblock.comp_true = cmd;
  83.     mycompblock.comp_alt = Nullcmd;
  84.     cmd = add_label(savestr("_SUB_"),make_ccmd(C_BLOCK,0,
  85.         Nullarg,mycompblock));
  86.     saw_return = FALSE;
  87.     cmd->c_flags |= CF_TERM;
  88.     }
  89.     sub->cmd = cmd;
  90.     if (perldb) {
  91.     STR *str;
  92.     STR *tmpstr = str_mortal(&str_undef);
  93.  
  94.     sprintf(buf,"%s:%ld",stab_val(curcmd->c_filestab)->str_ptr, subline);
  95.     str = str_make(buf,0);
  96.     str_cat(str,"-");
  97.     sprintf(buf,"%ld",(long)curcmd->c_line);
  98.     str_cat(str,buf);
  99.     stab_efullname(tmpstr,stab);
  100.     hstore(stab_xhash(DBsub), tmpstr->str_ptr, tmpstr->str_cur, str, 0);
  101.     }
  102.     Safefree(name);
  103.     return sub;
  104. }
  105.  
  106. SUBR *
  107. make_usub(name, ix, subaddr, filename)
  108. char *name;
  109. int ix;
  110. int (*subaddr)();
  111. char *filename;
  112. {
  113.     register SUBR *sub;
  114.     STAB *stab = stabent(name,allstabs);
  115.  
  116.     if (!stab)                /* unused function */
  117.     return Null(SUBR*);
  118.     if (sub = stab_sub(stab)) {
  119.     if (dowarn)
  120.         warn("Subroutine %s redefined",name);
  121.     if (!sub->usersub && sub->cmd) {
  122.         cmd_free(sub->cmd);
  123.         sub->cmd = Nullcmd;
  124.         afree(sub->tosave);
  125.     }
  126.     Safefree(sub);
  127.     }
  128.     Newz(101,sub,1,SUBR);
  129.     stab_sub(stab) = sub;
  130.     sub->filestab = fstab(filename);
  131.     sub->usersub = subaddr;
  132.     sub->userindex = ix;
  133.     return sub;
  134. }
  135.  
  136. void
  137. make_form(stab,fcmd)
  138. STAB *stab;
  139. FCMD *fcmd;
  140. {
  141.     if (stab_form(stab)) {
  142.     FCMD *tmpfcmd;
  143.     FCMD *nextfcmd;
  144.  
  145.     for (tmpfcmd = stab_form(stab); tmpfcmd; tmpfcmd = nextfcmd) {
  146.         nextfcmd = tmpfcmd->f_next;
  147.         if (tmpfcmd->f_expr)
  148.         arg_free(tmpfcmd->f_expr);
  149.         if (tmpfcmd->f_unparsed)
  150.         str_free(tmpfcmd->f_unparsed);
  151.         if (tmpfcmd->f_pre)
  152.         Safefree(tmpfcmd->f_pre);
  153.         Safefree(tmpfcmd);
  154.     }
  155.     }
  156.     stab_form(stab) = fcmd;
  157. }
  158.  
  159. CMD *
  160. block_head(tail)
  161. register CMD *tail;
  162. {
  163.     CMD *head;
  164.     register int opt;
  165.     register int last_opt = 0;
  166.     register STAB *last_stab = Nullstab;
  167.     register int count = 0;
  168.     register CMD *switchbeg = Nullcmd;
  169.  
  170.     if (tail == Nullcmd) {
  171.     return tail;
  172.     }
  173.     head = tail->c_head;
  174.  
  175.     for (tail = head; tail; tail = tail->c_next) {
  176.  
  177.     /* save one measly dereference at runtime */
  178.     if (tail->c_type == C_IF) {
  179.         if (!(tail->ucmd.ccmd.cc_alt = tail->ucmd.ccmd.cc_alt->c_next))
  180.         tail->c_flags |= CF_TERM;
  181.     }
  182.     else if (tail->c_type == C_EXPR) {
  183.         ARG *arg;
  184.  
  185.         if (tail->ucmd.acmd.ac_expr)
  186.         arg = tail->ucmd.acmd.ac_expr;
  187.         else
  188.         arg = tail->c_expr;
  189.         if (arg) {
  190.         if (arg->arg_type == O_RETURN)
  191.             tail->c_flags |= CF_TERM;
  192.         else if (arg->arg_type == O_ITEM && arg[1].arg_type == A_CMD)
  193.             tail->c_flags |= CF_TERM;
  194.         }
  195.     }
  196.     if (!tail->c_next)
  197.         tail->c_flags |= CF_TERM;
  198.  
  199.     if (tail->c_expr && (tail->c_flags & CF_OPTIMIZE) == CFT_FALSE)
  200.         opt_arg(tail,1, tail->c_type == C_EXPR);
  201.  
  202.     /* now do a little optimization on case-ish structures */
  203.     switch(tail->c_flags & (CF_OPTIMIZE|CF_FIRSTNEG|CF_INVERT)) {
  204.     case CFT_ANCHOR:
  205.     case CFT_STROP:
  206.         opt = (tail->c_flags & CF_NESURE) ? CFT_STROP : 0;
  207.         break;
  208.     case CFT_CCLASS:
  209.         opt = CFT_STROP;
  210.         break;
  211.     case CFT_NUMOP:
  212.         opt = (tail->c_slen == O_NE ? 0 : CFT_NUMOP);
  213.         if ((tail->c_flags&(CF_NESURE|CF_EQSURE)) != (CF_NESURE|CF_EQSURE))
  214.         opt = 0;
  215.         break;
  216.     default:
  217.         opt = 0;
  218.     }
  219.     if (opt && opt == last_opt && tail->c_stab == last_stab)
  220.         count++;
  221.     else {
  222.         if (count >= 3) {        /* is this the breakeven point? */
  223.         if (last_opt == CFT_NUMOP)
  224.             make_nswitch(switchbeg,count);
  225.         else
  226.             make_cswitch(switchbeg,count);
  227.         }
  228.         if (opt) {
  229.         count = 1;
  230.         switchbeg = tail;
  231.         }
  232.         else
  233.         count = 0;
  234.     }
  235.     last_opt = opt;
  236.     last_stab = tail->c_stab;
  237.     }
  238.     if (count >= 3) {        /* is this the breakeven point? */
  239.     if (last_opt == CFT_NUMOP)
  240.         make_nswitch(switchbeg,count);
  241.     else
  242.         make_cswitch(switchbeg,count);
  243.     }
  244.     return head;
  245. }
  246.  
  247. /* We've spotted a sequence of CMDs that all test the value of the same
  248.  * spat.  Thus we can insert a SWITCH in front and jump directly
  249.  * to the correct one.
  250.  */
  251. static void
  252. make_cswitch(head,count)
  253. register CMD *head;
  254. int count;
  255. {
  256.     register CMD *cur;
  257.     register CMD **loc;
  258.     register int i;
  259.     register int min = 255;
  260.     register int max = 0;
  261.  
  262.     /* make a new head in the exact same spot */
  263.     New(102,cur, 1, CMD);
  264.     StructCopy(head,cur,CMD);
  265.     Zero(head,1,CMD);
  266.     head->c_head = cur->c_head;
  267.     head->c_type = C_CSWITCH;
  268.     head->c_next = cur;        /* insert new cmd at front of list */
  269.     head->c_stab = cur->c_stab;
  270.  
  271.     Newz(103,loc,258,CMD*);
  272.     loc++;                /* lie a little */
  273.     while (count--) {
  274.     if ((cur->c_flags & CF_OPTIMIZE) == CFT_CCLASS) {
  275.         for (i = 0; i <= 255; i++) {
  276.         if (!loc[i] && cur->c_short->str_ptr[i>>3] & (1 << (i&7))) {
  277.             loc[i] = cur;
  278.             if (i < min)
  279.             min = i;
  280.             if (i > max)
  281.             max = i;
  282.         }
  283.         }
  284.     }
  285.     else {
  286.         i = *cur->c_short->str_ptr & 255;
  287.         if (!loc[i]) {
  288.         loc[i] = cur;
  289.         if (i < min)
  290.             min = i;
  291.         if (i > max)
  292.             max = i;
  293.         }
  294.     }
  295.     cur = cur->c_next;
  296.     }
  297.     max++;
  298.     if (min > 0)
  299.     Move(&loc[min],&loc[0], max - min, CMD*);
  300.     loc--;
  301.     min--;
  302.     max -= min;
  303.     for (i = 0; i <= max; i++)
  304.     if (!loc[i])
  305.         loc[i] = cur;
  306.     Renew(loc,max+1,CMD*);    /* chop it down to size */
  307.     head->ucmd.scmd.sc_offset = min;
  308.     head->ucmd.scmd.sc_max = max;
  309.     head->ucmd.scmd.sc_next = loc;
  310. }
  311.  
  312. static void
  313. make_nswitch(head,count)
  314. register CMD *head;
  315. int count;
  316. {
  317.     register CMD *cur = head;
  318.     register CMD **loc;
  319.     register int i;
  320.     register int min = 32767;
  321.     register int max = -32768;
  322.     int origcount = count;
  323.     double value;        /* or your money back! */
  324.     short changed;        /* so triple your money back! */
  325.  
  326.     while (count--) {
  327.     i = (int)str_gnum(cur->c_short);
  328.     value = (double)i;
  329.     if (value != cur->c_short->str_u.str_nval)
  330.         return;        /* fractional values--just forget it */
  331.     changed = i;
  332.     if (changed != i)
  333.         return;        /* too big for a short */
  334.     if (cur->c_slen == O_LE)
  335.         i++;
  336.     else if (cur->c_slen == O_GE)    /* we only do < or > here */
  337.         i--;
  338.     if (i < min)
  339.         min = i;
  340.     if (i > max)
  341.         max = i;
  342.     cur = cur->c_next;
  343.     }
  344.     count = origcount;
  345.     if (max - min > count * 2 + 10)        /* too sparse? */
  346.     return;
  347.  
  348.     /* now make a new head in the exact same spot */
  349.     New(104,cur, 1, CMD);
  350.     StructCopy(head,cur,CMD);
  351.     Zero(head,1,CMD);
  352.     head->c_head = cur->c_head;
  353.     head->c_type = C_NSWITCH;
  354.     head->c_next = cur;        /* insert new cmd at front of list */
  355.     head->c_stab = cur->c_stab;
  356.  
  357.     Newz(105,loc, max - min + 3, CMD*);
  358.     loc++;
  359.     max -= min;
  360.     max++;
  361.     while (count--) {
  362.     i = (int)str_gnum(cur->c_short);
  363.     i -= min;
  364.     switch(cur->c_slen) {
  365.     case O_LE:
  366.         i++;
  367.     case O_LT:
  368.         for (i--; i >= -1; i--)
  369.         if (!loc[i])
  370.             loc[i] = cur;
  371.         break;
  372.     case O_GE:
  373.         i--;
  374.     case O_GT:
  375.         for (i++; i <= max; i++)
  376.         if (!loc[i])
  377.             loc[i] = cur;
  378.         break;
  379.     case O_EQ:
  380.         if (!loc[i])
  381.         loc[i] = cur;
  382.         break;
  383.     }
  384.     cur = cur->c_next;
  385.     }
  386.     loc--;
  387.     min--;
  388.     max++;
  389.     for (i = 0; i <= max; i++)
  390.     if (!loc[i])
  391.         loc[i] = cur;
  392.     head->ucmd.scmd.sc_offset = min;
  393.     head->ucmd.scmd.sc_max = max;
  394.     head->ucmd.scmd.sc_next = loc;
  395. }
  396.  
  397. CMD *
  398. append_line(head,tail)
  399. register CMD *head;
  400. register CMD *tail;
  401. {
  402.     if (tail == Nullcmd)
  403.     return head;
  404.     if (!tail->c_head)            /* make sure tail is well formed */
  405.     tail->c_head = tail;
  406.     if (head != Nullcmd) {
  407.     tail = tail->c_head;        /* get to start of tail list */
  408.     if (!head->c_head)
  409.         head->c_head = head;    /* start a new head list */
  410.     while (head->c_next) {
  411.         head->c_next->c_head = head->c_head;
  412.         head = head->c_next;    /* get to end of head list */
  413.     }
  414.     head->c_next = tail;        /* link to end of old list */
  415.     tail->c_head = head->c_head;    /* propagate head pointer */
  416.     }
  417.     while (tail->c_next) {
  418.     tail->c_next->c_head = tail->c_head;
  419.     tail = tail->c_next;
  420.     }
  421.     return tail;
  422. }
  423.  
  424. CMD *
  425. dodb(cur)
  426. CMD *cur;
  427. {
  428.     register CMD *cmd;
  429.     register CMD *head = cur->c_head;
  430.     STR *str;
  431.  
  432.     if (!head)
  433.     head = cur;
  434.     if (!head->c_line)
  435.     return cur;
  436.     str = afetch(stab_xarray(curcmd->c_filestab),(int)head->c_line,FALSE);
  437.     if (str == &str_undef || str->str_nok)
  438.     return cur;
  439.     str->str_u.str_nval = (double)head->c_line;
  440.     str->str_nok = 1;
  441.     Newz(106,cmd,1,CMD);
  442.     str_magic(str, curcmd->c_filestab, 0, Nullch, 0);
  443.     str->str_magic->str_u.str_cmd = cmd;
  444.     cmd->c_type = C_EXPR;
  445.     cmd->ucmd.acmd.ac_stab = Nullstab;
  446.     cmd->ucmd.acmd.ac_expr = Nullarg;
  447.     cmd->c_expr = make_op(O_SUBR, 2,
  448.     stab2arg(A_WORD,DBstab),
  449.     Nullarg,
  450.     Nullarg);
  451.     /*SUPPRESS 53*/
  452.     cmd->c_flags |= CF_COND|CF_DBSUB|CFT_D0;
  453.     cmd->c_line = head->c_line;
  454.     cmd->c_label = head->c_label;
  455.     cmd->c_filestab = curcmd->c_filestab;
  456.     cmd->c_stash = curstash;
  457.     return append_line(cmd, cur);
  458. }
  459.  
  460. CMD *
  461. make_acmd(type,stab,cond,arg)
  462. int type;
  463. STAB *stab;
  464. ARG *cond;
  465. ARG *arg;
  466. {
  467.     register CMD *cmd;
  468.  
  469.     Newz(107,cmd,1,CMD);
  470.     cmd->c_type = type;
  471.     cmd->ucmd.acmd.ac_stab = stab;
  472.     cmd->ucmd.acmd.ac_expr = arg;
  473.     cmd->c_expr = cond;
  474.     if (cond)
  475.     cmd->c_flags |= CF_COND;
  476.     if (cmdline == NOLINE)
  477.     cmd->c_line = curcmd->c_line;
  478.     else {
  479.     cmd->c_line = cmdline;
  480.     cmdline = NOLINE;
  481.     }
  482.     cmd->c_filestab = curcmd->c_filestab;
  483.     cmd->c_stash = curstash;
  484.     if (perldb)
  485.     cmd = dodb(cmd);
  486.     return cmd;
  487. }
  488.  
  489. CMD *
  490. make_ccmd(type,debuggable,arg,cblock)
  491. int type;
  492. int debuggable;
  493. ARG *arg;
  494. struct compcmd cblock;
  495. {
  496.     register CMD *cmd;
  497.  
  498.     Newz(108,cmd, 1, CMD);
  499.     cmd->c_type = type;
  500.     cmd->c_expr = arg;
  501.     cmd->ucmd.ccmd.cc_true = cblock.comp_true;
  502.     cmd->ucmd.ccmd.cc_alt = cblock.comp_alt;
  503.     if (arg)
  504.     cmd->c_flags |= CF_COND;
  505.     if (cmdline == NOLINE)
  506.     cmd->c_line = curcmd->c_line;
  507.     else {
  508.     cmd->c_line = cmdline;
  509.     cmdline = NOLINE;
  510.     }
  511.     cmd->c_filestab = curcmd->c_filestab;
  512.     cmd->c_stash = curstash;
  513.     if (perldb && debuggable)
  514.     cmd = dodb(cmd);
  515.     return cmd;
  516. }
  517.  
  518. CMD *
  519. make_icmd(type,arg,cblock)
  520. int type;
  521. ARG *arg;
  522. struct compcmd cblock;
  523. {
  524.     register CMD *cmd;
  525.     register CMD *alt;
  526.     register CMD *cur;
  527.     register CMD *head;
  528.     struct compcmd ncblock;
  529.  
  530.     Newz(109,cmd, 1, CMD);
  531.     head = cmd;
  532.     cmd->c_type = type;
  533.     cmd->c_expr = arg;
  534.     cmd->ucmd.ccmd.cc_true = cblock.comp_true;
  535.     cmd->ucmd.ccmd.cc_alt = cblock.comp_alt;
  536.     if (arg)
  537.     cmd->c_flags |= CF_COND;
  538.     if (cmdline == NOLINE)
  539.     cmd->c_line = curcmd->c_line;
  540.     else {
  541.     cmd->c_line = cmdline;
  542.     cmdline = NOLINE;
  543.     }
  544.     cmd->c_filestab = curcmd->c_filestab;
  545.     cmd->c_stash = curstash;
  546.     cur = cmd;
  547.     alt = cblock.comp_alt;
  548.     while (alt && alt->c_type == C_ELSIF) {
  549.     cur = alt;
  550.     alt = alt->ucmd.ccmd.cc_alt;
  551.     }
  552.     if (alt) {            /* a real life ELSE at the end? */
  553.     ncblock.comp_true = alt;
  554.     ncblock.comp_alt = Nullcmd;
  555.     alt = append_line(cur,make_ccmd(C_ELSE,1,Nullarg,ncblock));
  556.     cur->ucmd.ccmd.cc_alt = alt;
  557.     }
  558.     else
  559.     alt = cur;        /* no ELSE, so cur is proxy ELSE */
  560.  
  561.     cur = cmd;
  562.     while (cmd) {        /* now point everyone at the ELSE */
  563.     cur = cmd;
  564.     cmd = cur->ucmd.ccmd.cc_alt;
  565.     cur->c_head = head;
  566.     if (cur->c_type == C_ELSIF)
  567.         cur->c_type = C_IF;
  568.     if (cur->c_type == C_IF)
  569.         cur->ucmd.ccmd.cc_alt = alt;
  570.     if (cur == alt)
  571.         break;
  572.     cur->c_next = cmd;
  573.     }
  574.     if (perldb)
  575.     cur = dodb(cur);
  576.     return cur;
  577. }
  578.  
  579. void
  580. opt_arg(cmd,fliporflop,acmd)
  581. register CMD *cmd;
  582. int fliporflop;
  583. int acmd;
  584. {
  585.     register ARG *arg;
  586.     int opt = CFT_EVAL;
  587.     int sure = 0;
  588.     ARG *arg2;
  589.     int context = 0;    /* 0 = normal, 1 = before &&, 2 = before || */
  590.     int flp = fliporflop;
  591.  
  592.     if (!cmd)
  593.     return;
  594.     if (!(arg = cmd->c_expr)) {
  595.     cmd->c_flags &= ~CF_COND;
  596.     return;
  597.     }
  598.  
  599.     /* Can we turn && and || into if and unless? */
  600.  
  601.     if (acmd && !cmd->ucmd.acmd.ac_expr && !(cmd->c_flags & CF_TERM) &&
  602.       (arg->arg_type == O_AND || arg->arg_type == O_OR) ) {
  603.     dehoist(arg,1);
  604.     arg[2].arg_type &= A_MASK;    /* don't suppress eval */
  605.     dehoist(arg,2);
  606.     cmd->ucmd.acmd.ac_expr = arg[2].arg_ptr.arg_arg;
  607.     cmd->c_expr = arg[1].arg_ptr.arg_arg;
  608.     if (arg->arg_type == O_OR)
  609.         cmd->c_flags ^= CF_INVERT;        /* || is like unless */
  610.     arg->arg_len = 0;
  611.     free_arg(arg);
  612.     arg = cmd->c_expr;
  613.     }
  614.  
  615.     /* Turn "if (!expr)" into "unless (expr)" */
  616.  
  617.     if (!(cmd->c_flags & CF_TERM)) {        /* unless return value wanted */
  618.     while (arg->arg_type == O_NOT) {
  619.         dehoist(arg,1);
  620.         cmd->c_flags ^= CF_INVERT;        /* flip sense of cmd */
  621.         cmd->c_expr = arg[1].arg_ptr.arg_arg; /* hoist the rest of expr */
  622.         free_arg(arg);
  623.         arg = cmd->c_expr;            /* here we go again */
  624.     }
  625.     }
  626.  
  627.     if (!arg->arg_len) {        /* sanity check */
  628.     cmd->c_flags |= opt;
  629.     return;
  630.     }
  631.  
  632.     /* for "cond .. cond" we set up for the initial check */
  633.  
  634.     if (arg->arg_type == O_FLIP)
  635.     context |= 4;
  636.  
  637.     /* for "cond && expr" and "cond || expr" we can ignore expr, sort of */
  638.  
  639.   morecontext:
  640.     if (arg->arg_type == O_AND)
  641.     context |= 1;
  642.     else if (arg->arg_type == O_OR)
  643.     context |= 2;
  644.     if (context && (arg[flp].arg_type & A_MASK) == A_EXPR) {
  645.     arg = arg[flp].arg_ptr.arg_arg;
  646.     flp = 1;
  647.     if (arg->arg_type == O_AND || arg->arg_type == O_OR)
  648.         goto morecontext;
  649.     }
  650.     if ((context & 3) == 3)
  651.     return;
  652.  
  653.     if (arg[flp].arg_flags & (AF_PRE|AF_POST)) {
  654.     cmd->c_flags |= opt;
  655.     if (acmd && !cmd->ucmd.acmd.ac_expr && !(cmd->c_flags & CF_TERM)
  656.       && cmd->c_expr->arg_type == O_ITEM) {
  657.         arg[flp].arg_flags &= ~AF_POST;    /* prefer ++$foo to $foo++ */
  658.         arg[flp].arg_flags |= AF_PRE;    /*  if value not wanted */
  659.     }
  660.     return;                /* side effect, can't optimize */
  661.     }
  662.  
  663.     if (arg->arg_type == O_ITEM || arg->arg_type == O_FLIP ||
  664.       arg->arg_type == O_AND || arg->arg_type == O_OR) {
  665.     if ((arg[flp].arg_type & A_MASK) == A_SINGLE) {
  666.         opt = (str_true(arg[flp].arg_ptr.arg_str) ? CFT_TRUE : CFT_FALSE);
  667.         cmd->c_short = str_smake(arg[flp].arg_ptr.arg_str);
  668.         goto literal;
  669.     }
  670.     else if ((arg[flp].arg_type & A_MASK) == A_STAB ||
  671.       (arg[flp].arg_type & A_MASK) == A_LVAL) {
  672.         cmd->c_stab  = arg[flp].arg_ptr.arg_stab;
  673.         if (!context)
  674.         arg[flp].arg_ptr.arg_stab = Nullstab;
  675.         opt = CFT_REG;
  676.       literal:
  677.         if (!context) {    /* no && or ||? */
  678.         arg_free(arg);
  679.         cmd->c_expr = Nullarg;
  680.         }
  681.         if (!(context & 1))
  682.         cmd->c_flags |= CF_EQSURE;
  683.         if (!(context & 2))
  684.         cmd->c_flags |= CF_NESURE;
  685.     }
  686.     }
  687.     else if (arg->arg_type == O_MATCH || arg->arg_type == O_SUBST ||
  688.          arg->arg_type == O_NMATCH || arg->arg_type == O_NSUBST) {
  689.     if ((arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) &&
  690.         (arg[2].arg_type & A_MASK) == A_SPAT &&
  691.         arg[2].arg_ptr.arg_spat->spat_short &&
  692.         (arg->arg_type == O_SUBST || arg->arg_type == O_NSUBST ||
  693.          (arg[2].arg_ptr.arg_spat->spat_flags & SPAT_GLOBAL) == 0 )) {
  694.         cmd->c_stab  = arg[1].arg_ptr.arg_stab;
  695.         cmd->c_short = str_smake(arg[2].arg_ptr.arg_spat->spat_short);
  696.         cmd->c_slen  = arg[2].arg_ptr.arg_spat->spat_slen;
  697.         if (arg[2].arg_ptr.arg_spat->spat_flags & SPAT_ALL &&
  698.         !(arg[2].arg_ptr.arg_spat->spat_flags & SPAT_ONCE) &&
  699.         (arg->arg_type == O_MATCH || arg->arg_type == O_NMATCH) )
  700.         sure |= CF_EQSURE;        /* (SUBST must be forced even */
  701.                         /* if we know it will work.) */
  702.         if (arg->arg_type != O_SUBST) {
  703.         str_free(arg[2].arg_ptr.arg_spat->spat_short);
  704.         arg[2].arg_ptr.arg_spat->spat_short = Nullstr;
  705.         arg[2].arg_ptr.arg_spat->spat_slen = 0; /* only one chk */
  706.         }
  707.         sure |= CF_NESURE;        /* normally only sure if it fails */
  708.         if (arg->arg_type == O_NMATCH || arg->arg_type == O_NSUBST)
  709.         cmd->c_flags |= CF_FIRSTNEG;
  710.         if (context & 1) {        /* only sure if thing is false */
  711.         if (cmd->c_flags & CF_FIRSTNEG)
  712.             sure &= ~CF_NESURE;
  713.         else
  714.             sure &= ~CF_EQSURE;
  715.         }
  716.         else if (context & 2) {    /* only sure if thing is true */
  717.         if (cmd->c_flags & CF_FIRSTNEG)
  718.             sure &= ~CF_EQSURE;
  719.         else
  720.             sure &= ~CF_NESURE;
  721.         }
  722.         if (sure & (CF_EQSURE|CF_NESURE)) {    /* if we know anything*/
  723.         if (arg[2].arg_ptr.arg_spat->spat_flags & SPAT_SCANFIRST)
  724.             opt = CFT_SCAN;
  725.         else
  726.             opt = CFT_ANCHOR;
  727.         if (sure == (CF_EQSURE|CF_NESURE)    /* really sure? */
  728.             && arg->arg_type == O_MATCH
  729.             && context & 4
  730.             && fliporflop == 1) {
  731.             spat_free(arg[2].arg_ptr.arg_spat);
  732.             arg[2].arg_ptr.arg_spat = Nullspat;    /* don't do twice */
  733.         }
  734.         else
  735.             cmd->c_spat = arg[2].arg_ptr.arg_spat;
  736.         cmd->c_flags |= sure;
  737.         }
  738.     }
  739.     }
  740.     else if (arg->arg_type == O_SEQ || arg->arg_type == O_SNE ||
  741.          arg->arg_type == O_SLT || arg->arg_type == O_SGT) {
  742.     if (arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) {
  743.         if (arg[2].arg_type == A_SINGLE) {
  744.         /*SUPPRESS 594*/
  745.         char *junk = str_get(arg[2].arg_ptr.arg_str);
  746.  
  747.         cmd->c_stab  = arg[1].arg_ptr.arg_stab;
  748.         cmd->c_short = str_smake(arg[2].arg_ptr.arg_str);
  749.         cmd->c_slen  = cmd->c_short->str_cur+1;
  750.         switch (arg->arg_type) {
  751.         case O_SLT: case O_SGT:
  752.             sure |= CF_EQSURE;
  753.             cmd->c_flags |= CF_FIRSTNEG;
  754.             break;
  755.         case O_SNE:
  756.             cmd->c_flags |= CF_FIRSTNEG;
  757.             /* FALL THROUGH */
  758.         case O_SEQ:
  759.             sure |= CF_NESURE|CF_EQSURE;
  760.             break;
  761.         }
  762.         if (context & 1) {    /* only sure if thing is false */
  763.             if (cmd->c_flags & CF_FIRSTNEG)
  764.             sure &= ~CF_NESURE;
  765.             else
  766.             sure &= ~CF_EQSURE;
  767.         }
  768.         else if (context & 2) { /* only sure if thing is true */
  769.             if (cmd->c_flags & CF_FIRSTNEG)
  770.             sure &= ~CF_EQSURE;
  771.             else
  772.             sure &= ~CF_NESURE;
  773.         }
  774.         if (sure & (CF_EQSURE|CF_NESURE)) {
  775.             opt = CFT_STROP;
  776.             cmd->c_flags |= sure;
  777.         }
  778.         }
  779.     }
  780.     }
  781.     else if (arg->arg_type == O_EQ || arg->arg_type == O_NE ||
  782.          arg->arg_type == O_LE || arg->arg_type == O_GE ||
  783.          arg->arg_type == O_LT || arg->arg_type == O_GT) {
  784.     if (arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) {
  785.         if (arg[2].arg_type == A_SINGLE) {
  786.         cmd->c_stab  = arg[1].arg_ptr.arg_stab;
  787.         if (dowarn) {
  788.             STR *str = arg[2].arg_ptr.arg_str;
  789.  
  790.             if ((!str->str_nok && !looks_like_number(str)))
  791.             warn("Possible use of == on string value");
  792.         }
  793.         cmd->c_short = str_nmake(str_gnum(arg[2].arg_ptr.arg_str));
  794.         cmd->c_slen = arg->arg_type;
  795.         sure |= CF_NESURE|CF_EQSURE;
  796.         if (context & 1) {    /* only sure if thing is false */
  797.             sure &= ~CF_EQSURE;
  798.         }
  799.         else if (context & 2) { /* only sure if thing is true */
  800.             sure &= ~CF_NESURE;
  801.         }
  802.         if (sure & (CF_EQSURE|CF_NESURE)) {
  803.             opt = CFT_NUMOP;
  804.             cmd->c_flags |= sure;
  805.         }
  806.         }
  807.     }
  808.     }
  809.     else if (arg->arg_type == O_ASSIGN &&
  810.          (arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) &&
  811.          arg[1].arg_ptr.arg_stab == defstab &&
  812.          arg[2].arg_type == A_EXPR ) {
  813.     arg2 = arg[2].arg_ptr.arg_arg;
  814.     if (arg2->arg_type == O_ITEM && arg2[1].arg_type == A_READ) {
  815.         opt = CFT_GETS;
  816.         cmd->c_stab = arg2[1].arg_ptr.arg_stab;
  817.         if (!(stab_io(arg2[1].arg_ptr.arg_stab)->flags & IOF_ARGV)) {
  818.         free_arg(arg2);
  819.         arg[2].arg_ptr.arg_arg = Nullarg;
  820.         free_arg(arg);
  821.         cmd->c_expr = Nullarg;
  822.         }
  823.     }
  824.     }
  825.     else if (arg->arg_type == O_CHOP &&
  826.          (arg[1].arg_type == A_STAB || arg[1].arg_type == A_LVAL) ) {
  827.     opt = CFT_CHOP;
  828.     cmd->c_stab = arg[1].arg_ptr.arg_stab;
  829.     free_arg(arg);
  830.     cmd->c_expr = Nullarg;
  831.     }
  832.     if (context & 4)
  833.     opt |= CF_FLIP;
  834.     cmd->c_flags |= opt;
  835.  
  836.     if (cmd->c_flags & CF_FLIP) {
  837.     if (fliporflop == 1) {
  838.         arg = cmd->c_expr;    /* get back to O_FLIP arg */
  839.         New(110,arg[3].arg_ptr.arg_cmd, 1, CMD);
  840.         Copy(cmd, arg[3].arg_ptr.arg_cmd, 1, CMD);
  841.         New(111,arg[4].arg_ptr.arg_cmd,1,CMD);
  842.         Copy(cmd, arg[4].arg_ptr.arg_cmd, 1, CMD);
  843.         opt_arg(arg[4].arg_ptr.arg_cmd,2,acmd);
  844.         arg->arg_len = 2;        /* this is a lie */
  845.     }
  846.     else {
  847.         if ((opt & CF_OPTIMIZE) == CFT_EVAL)
  848.         cmd->c_flags = (cmd->c_flags & ~CF_OPTIMIZE) | CFT_UNFLIP;
  849.     }
  850.     }
  851. }
  852.  
  853. CMD *
  854. add_label(lbl,cmd)
  855. char *lbl;
  856. register CMD *cmd;
  857. {
  858.     if (cmd)
  859.     cmd->c_label = lbl;
  860.     return cmd;
  861. }
  862.  
  863. CMD *
  864. addcond(cmd, arg)
  865. register CMD *cmd;
  866. register ARG *arg;
  867. {
  868.     cmd->c_expr = arg;
  869.     cmd->c_flags |= CF_COND;
  870.     return cmd;
  871. }
  872.  
  873. CMD *
  874. addloop(cmd, arg)
  875. register CMD *cmd;
  876. register ARG *arg;
  877. {
  878.     void while_io();
  879.  
  880.     cmd->c_expr = arg;
  881.     cmd->c_flags |= CF_COND|CF_LOOP;
  882.  
  883.     if (!(cmd->c_flags & CF_INVERT))
  884.     while_io(cmd);        /* add $_ =, if necessary */
  885.  
  886.     if (cmd->c_type == C_BLOCK)
  887.     cmd->c_flags &= ~CF_COND;
  888.     else {
  889.     arg = cmd->ucmd.acmd.ac_expr;
  890.     if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_CMD)
  891.         cmd->c_flags &= ~CF_COND;  /* "do {} while" happens at least once */
  892.     if (arg && (arg->arg_flags & AF_DEPR) &&
  893.       (arg->arg_type == O_SUBR || arg->arg_type == O_DBSUBR) )
  894.         cmd->c_flags &= ~CF_COND;  /* likewise for "do subr() while" */
  895.     }
  896.     return cmd;
  897. }
  898.  
  899. CMD *
  900. invert(cmd)
  901. CMD *cmd;
  902. {
  903.     register CMD *targ = cmd;
  904.     if (targ->c_head)
  905.     targ = targ->c_head;
  906.     if (targ->c_flags & CF_DBSUB)
  907.     targ = targ->c_next;
  908.     targ->c_flags ^= CF_INVERT;
  909.     return cmd;
  910. }
  911.  
  912. void
  913. cpy7bit(d,s,l)
  914. register char *d;
  915. register char *s;
  916. register int l;
  917. {
  918.     while (l--)
  919.     *d++ = *s++ & 127;
  920.     *d = '\0';
  921. }
  922.  
  923. int
  924. yyerror(s)
  925. char *s;
  926. {
  927.     char tmpbuf[258];
  928.     char tmp2buf[258];
  929.     char *tname = tmpbuf;
  930.  
  931.     if (bufptr > oldoldbufptr && bufptr - oldoldbufptr < 200 &&
  932.       oldoldbufptr != oldbufptr && oldbufptr != bufptr) {
  933.     while (isSPACE(*oldoldbufptr))
  934.         oldoldbufptr++;
  935.     cpy7bit(tmp2buf, oldoldbufptr, bufptr - oldoldbufptr);
  936.     sprintf(tname,"next 2 tokens \"%s\"",tmp2buf);
  937.     }
  938.     else if (bufptr > oldbufptr && bufptr - oldbufptr < 200 &&
  939.       oldbufptr != bufptr) {
  940.     while (isSPACE(*oldbufptr))
  941.         oldbufptr++;
  942.     cpy7bit(tmp2buf, oldbufptr, bufptr - oldbufptr);
  943.     sprintf(tname,"next token \"%s\"",tmp2buf);
  944.     }
  945.     else if (yychar > 256)
  946.     tname = "next token ???";
  947.     else if (!yychar)
  948.     (void)strcpy(tname,"at EOF");
  949.     else if (yychar < 32)
  950.     (void)sprintf(tname,"next char ^%c",yychar+64);
  951.     else if (yychar == 127)
  952.     (void)strcpy(tname,"at EOF");
  953.     else
  954.     (void)sprintf(tname,"next char %c",yychar);
  955.     (void)sprintf(buf, "%s in file %s at line %d, %s\n",
  956.       s,stab_val(curcmd->c_filestab)->str_ptr,curcmd->c_line,tname);
  957.     if (curcmd->c_line == multi_end && multi_start < multi_end)
  958.     sprintf(buf+strlen(buf),
  959.       "  (Might be a runaway multi-line %c%c string starting on line %d)\n",
  960.       multi_open,multi_close,multi_start);
  961.     if (in_eval)
  962.     str_cat(stab_val(stabent("@",TRUE)),buf);
  963.     else
  964.     fputs(buf,stderr);
  965.     if (++error_count >= 10)
  966.     fatal("%s has too many errors.\n",
  967.     stab_val(curcmd->c_filestab)->str_ptr);
  968. }
  969.  
  970. void
  971. while_io(cmd)
  972. register CMD *cmd;
  973. {
  974.     register ARG *arg = cmd->c_expr;
  975.     STAB *asgnstab;
  976.  
  977.     /* hoist "while (<channel>)" up into command block */
  978.  
  979.     if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_READ) {
  980.     cmd->c_flags &= ~CF_OPTIMIZE;    /* clear optimization type */
  981.     cmd->c_flags |= CFT_GETS;    /* and set it to do the input */
  982.     cmd->c_stab = arg[1].arg_ptr.arg_stab;
  983.     if (stab_io(arg[1].arg_ptr.arg_stab)->flags & IOF_ARGV) {
  984.         cmd->c_expr = l(make_op(O_ASSIGN, 2,    /* fake up "$_ =" */
  985.            stab2arg(A_LVAL,defstab), arg, Nullarg));
  986.     }
  987.     else {
  988.         free_arg(arg);
  989.         cmd->c_expr = Nullarg;
  990.     }
  991.     }
  992.     else if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_INDREAD) {
  993.     cmd->c_flags &= ~CF_OPTIMIZE;    /* clear optimization type */
  994.     cmd->c_flags |= CFT_INDGETS;    /* and set it to do the input */
  995.     cmd->c_stab = arg[1].arg_ptr.arg_stab;
  996.     free_arg(arg);
  997.     cmd->c_expr = Nullarg;
  998.     }
  999.     else if (arg && arg->arg_type == O_ITEM && arg[1].arg_type == A_GLOB) {
  1000.     if ((cmd->c_flags & CF_OPTIMIZE) == CFT_ARRAY)
  1001.         asgnstab = cmd->c_stab;
  1002.     else
  1003.         asgnstab = defstab;
  1004.     cmd->c_expr = l(make_op(O_ASSIGN, 2,    /* fake up "$foo =" */
  1005.        stab2arg(A_LVAL,asgnstab), arg, Nullarg));
  1006.     cmd->c_flags &= ~CF_OPTIMIZE;    /* clear optimization type */
  1007.     }
  1008. }
  1009.  
  1010. CMD *
  1011. wopt(cmd)
  1012. register CMD *cmd;
  1013. {
  1014.     register CMD *tail;
  1015.     CMD *newtail;
  1016.     register int i;
  1017.  
  1018.     if (cmd->c_expr && (cmd->c_flags & CF_OPTIMIZE) == CFT_FALSE)
  1019.     opt_arg(cmd,1, cmd->c_type == C_EXPR);
  1020.  
  1021.     while_io(cmd);        /* add $_ =, if necessary */
  1022.  
  1023.     /* First find the end of the true list */
  1024.  
  1025.     tail = cmd->ucmd.ccmd.cc_true;
  1026.     if (tail == Nullcmd)
  1027.     return cmd;
  1028.     New(112,newtail, 1, CMD);    /* guaranteed continue */
  1029.     for (;;) {
  1030.     /* optimize "next" to point directly to continue block */
  1031.     if (tail->c_type == C_EXPR &&
  1032.         tail->ucmd.acmd.ac_expr &&
  1033.         tail->ucmd.acmd.ac_expr->arg_type == O_NEXT &&
  1034.         (tail->ucmd.acmd.ac_expr->arg_len == 0 ||
  1035.          (cmd->c_label &&
  1036.           strEQ(cmd->c_label,
  1037.             tail->ucmd.acmd.ac_expr[1].arg_ptr.arg_str->str_ptr) )))
  1038.     {
  1039.         arg_free(tail->ucmd.acmd.ac_expr);
  1040.         tail->ucmd.acmd.ac_expr = Nullarg;
  1041.         tail->c_type = C_NEXT;
  1042.         if (cmd->ucmd.ccmd.cc_alt != Nullcmd)
  1043.         tail->ucmd.ccmd.cc_alt = cmd->ucmd.ccmd.cc_alt;
  1044.         else
  1045.         tail->ucmd.ccmd.cc_alt = newtail;
  1046.         tail->ucmd.ccmd.cc_true = Nullcmd;
  1047.     }
  1048.     else if (tail->c_type == C_IF && !tail->ucmd.ccmd.cc_alt) {
  1049.         if (cmd->ucmd.ccmd.cc_alt != Nullcmd)
  1050.         tail->ucmd.ccmd.cc_alt = cmd->ucmd.ccmd.cc_alt;
  1051.         else
  1052.         tail->ucmd.ccmd.cc_alt = newtail;
  1053.     }
  1054.     else if (tail->c_type == C_CSWITCH || tail->c_type == C_NSWITCH) {
  1055.         if (cmd->ucmd.ccmd.cc_alt != Nullcmd) {
  1056.         for (i = tail->ucmd.scmd.sc_max; i >= 0; i--)
  1057.             if (!tail->ucmd.scmd.sc_next[i])
  1058.             tail->ucmd.scmd.sc_next[i] = cmd->ucmd.ccmd.cc_alt;
  1059.         }
  1060.         else {
  1061.         for (i = tail->ucmd.scmd.sc_max; i >= 0; i--)
  1062.             if (!tail->ucmd.scmd.sc_next[i])
  1063.             tail->ucmd.scmd.sc_next[i] = newtail;
  1064.         }
  1065.     }
  1066.  
  1067.     if (!tail->c_next)
  1068.         break;
  1069.     tail = tail->c_next;
  1070.     }
  1071.  
  1072.     /* if there's a continue block, link it to true block and find end */
  1073.  
  1074.     if (cmd->ucmd.ccmd.cc_alt != Nullcmd) {
  1075.     tail->c_next = cmd->ucmd.ccmd.cc_alt;
  1076.     tail = tail->c_next;
  1077.     for (;;) {
  1078.         /* optimize "next" to point directly to continue block */
  1079.         if (tail->c_type == C_EXPR &&
  1080.         tail->ucmd.acmd.ac_expr &&
  1081.         tail->ucmd.acmd.ac_expr->arg_type == O_NEXT &&
  1082.         (tail->ucmd.acmd.ac_expr->arg_len == 0 ||
  1083.          (cmd->c_label &&
  1084.           strEQ(cmd->c_label,
  1085.             tail->ucmd.acmd.ac_expr[1].arg_ptr.arg_str->str_ptr) )))
  1086.         {
  1087.         arg_free(tail->ucmd.acmd.ac_expr);
  1088.         tail->ucmd.acmd.ac_expr = Nullarg;
  1089.         tail->c_type = C_NEXT;
  1090.         tail->ucmd.ccmd.cc_alt = newtail;
  1091.         tail->ucmd.ccmd.cc_true = Nullcmd;
  1092.         }
  1093.         else if (tail->c_type == C_IF && !tail->ucmd.ccmd.cc_alt) {
  1094.         tail->ucmd.ccmd.cc_alt = newtail;
  1095.         }
  1096.         else if (tail->c_type == C_CSWITCH || tail->c_type == C_NSWITCH) {
  1097.         for (i = tail->ucmd.scmd.sc_max; i >= 0; i--)
  1098.             if (!tail->ucmd.scmd.sc_next[i])
  1099.             tail->ucmd.scmd.sc_next[i] = newtail;
  1100.         }
  1101.  
  1102.         if (!tail->c_next)
  1103.         break;
  1104.         tail = tail->c_next;
  1105.     }
  1106.     /*SUPPRESS 530*/
  1107.     for ( ; tail->c_next; tail = tail->c_next) ;
  1108.     }
  1109.  
  1110.     /* Here's the real trick: link the end of the list back to the beginning,
  1111.      * inserting a "last" block to break out of the loop.  This saves one or
  1112.      * two procedure calls every time through the loop, because of how cmd_exec
  1113.      * does tail recursion.
  1114.      */
  1115.  
  1116.     tail->c_next = newtail;
  1117.     tail = newtail;
  1118.     if (!cmd->ucmd.ccmd.cc_alt)
  1119.     cmd->ucmd.ccmd.cc_alt = tail;    /* every loop has a continue now */
  1120.  
  1121. #ifndef lint
  1122.     Copy((char *)cmd, (char *)tail, 1, CMD);
  1123. #endif
  1124.     tail->c_type = C_EXPR;
  1125.     tail->c_flags ^= CF_INVERT;        /* turn into "last unless" */
  1126.     tail->c_next = tail->ucmd.ccmd.cc_true;    /* loop directly back to top */
  1127.     tail->ucmd.acmd.ac_expr = make_op(O_LAST,0,Nullarg,Nullarg,Nullarg);
  1128.     tail->ucmd.acmd.ac_stab = Nullstab;
  1129.     return cmd;
  1130. }
  1131.  
  1132. CMD *
  1133. over(eachstab,cmd)
  1134. STAB *eachstab;
  1135. register CMD *cmd;
  1136. {
  1137.     /* hoist "for $foo (@bar)" up into command block */
  1138.  
  1139.     cmd->c_flags &= ~CF_OPTIMIZE;    /* clear optimization type */
  1140.     cmd->c_flags |= CFT_ARRAY;        /* and set it to do the iteration */
  1141.     cmd->c_stab = eachstab;
  1142.     cmd->c_short = Str_new(23,0);    /* just to save a field in struct cmd */
  1143.     cmd->c_short->str_u.str_useful = -1;
  1144.  
  1145.     return cmd;
  1146. }
  1147.  
  1148. void
  1149. cmd_free(cmd)
  1150. register CMD *cmd;
  1151. {
  1152.     register CMD *tofree;
  1153.     register CMD *head = cmd;
  1154.  
  1155.     if (!cmd)
  1156.     return;
  1157.     if (cmd->c_head != cmd)
  1158.     warn("Malformed cmd links\n");
  1159.     while (cmd) {
  1160.     if (cmd->c_type != C_WHILE) {    /* WHILE block is duplicated */
  1161.         if (cmd->c_label) {
  1162.         Safefree(cmd->c_label);
  1163.         cmd->c_label = Nullch;
  1164.         }
  1165.         if (cmd->c_short) {
  1166.         str_free(cmd->c_short);
  1167.         cmd->c_short = Nullstr;
  1168.         }
  1169.         if (cmd->c_expr) {
  1170.         arg_free(cmd->c_expr);
  1171.         cmd->c_expr = Nullarg;
  1172.         }
  1173.     }
  1174.     switch (cmd->c_type) {
  1175.     case C_WHILE:
  1176.     case C_BLOCK:
  1177.     case C_ELSE:
  1178.     case C_IF:
  1179.         if (cmd->ucmd.ccmd.cc_true) {
  1180.         cmd_free(cmd->ucmd.ccmd.cc_true);
  1181.         cmd->ucmd.ccmd.cc_true = Nullcmd;
  1182.         }
  1183.         break;
  1184.     case C_EXPR:
  1185.         if (cmd->ucmd.acmd.ac_expr) {
  1186.         arg_free(cmd->ucmd.acmd.ac_expr);
  1187.         cmd->ucmd.acmd.ac_expr = Nullarg;
  1188.         }
  1189.         break;
  1190.     }
  1191.     tofree = cmd;
  1192.     cmd = cmd->c_next;
  1193.     if (tofree != head)        /* to get Saber to shut up */
  1194.         Safefree(tofree);
  1195.     if (cmd && cmd == head)        /* reached end of while loop */
  1196.         break;
  1197.     }
  1198.     Safefree(head);
  1199. }
  1200.  
  1201. void
  1202. arg_free(arg)
  1203. register ARG *arg;
  1204. {
  1205.     register int i;
  1206.  
  1207.     if (!arg)
  1208.     return;
  1209.     for (i = 1; i <= arg->arg_len; i++) {
  1210.     switch (arg[i].arg_type & A_MASK) {
  1211.     case A_NULL:
  1212.         if (arg->arg_type == O_TRANS) {
  1213.         Safefree(arg[i].arg_ptr.arg_cval);
  1214.         arg[i].arg_ptr.arg_cval = Nullch;
  1215.         }
  1216.         break;
  1217.     case A_LEXPR:
  1218.         if (arg->arg_type == O_AASSIGN &&
  1219.           arg[i].arg_ptr.arg_arg->arg_type == O_LARRAY) {
  1220.         char *name = 
  1221.           stab_name(arg[i].arg_ptr.arg_arg[1].arg_ptr.arg_stab);
  1222.  
  1223.         if (strnEQ("_GEN_",name, 5))    /* array for foreach */
  1224.             hdelete(defstash,name,strlen(name));
  1225.         }
  1226.         /* FALL THROUGH */
  1227.     case A_EXPR:
  1228.         arg_free(arg[i].arg_ptr.arg_arg);
  1229.         arg[i].arg_ptr.arg_arg = Nullarg;
  1230.         break;
  1231.     case A_CMD:
  1232.         cmd_free(arg[i].arg_ptr.arg_cmd);
  1233.         arg[i].arg_ptr.arg_cmd = Nullcmd;
  1234.         break;
  1235.     case A_WORD:
  1236.     case A_STAB:
  1237.     case A_LVAL:
  1238.     case A_READ:
  1239.     case A_GLOB:
  1240.     case A_ARYLEN:
  1241.     case A_LARYLEN:
  1242.     case A_ARYSTAB:
  1243.     case A_LARYSTAB:
  1244.         break;
  1245.     case A_SINGLE:
  1246.     case A_DOUBLE:
  1247.     case A_BACKTICK:
  1248.         str_free(arg[i].arg_ptr.arg_str);
  1249.         arg[i].arg_ptr.arg_str = Nullstr;
  1250.         break;
  1251.     case A_SPAT:
  1252.         spat_free(arg[i].arg_ptr.arg_spat);
  1253.         arg[i].arg_ptr.arg_spat = Nullspat;
  1254.         break;
  1255.     }
  1256.     }
  1257.     free_arg(arg);
  1258. }
  1259.  
  1260. void
  1261. spat_free(spat)
  1262. register SPAT *spat;
  1263. {
  1264.     register SPAT *sp;
  1265.     HENT *entry;
  1266.  
  1267.     if (!spat)
  1268.     return;
  1269.     if (spat->spat_runtime) {
  1270.     arg_free(spat->spat_runtime);
  1271.     spat->spat_runtime = Nullarg;
  1272.     }
  1273.     if (spat->spat_repl) {
  1274.     arg_free(spat->spat_repl);
  1275.     spat->spat_repl = Nullarg;
  1276.     }
  1277.     if (spat->spat_short) {
  1278.     str_free(spat->spat_short);
  1279.     spat->spat_short = Nullstr;
  1280.     }
  1281.     if (spat->spat_regexp) {
  1282.     regfree(spat->spat_regexp);
  1283.     spat->spat_regexp = Null(REGEXP*);
  1284.     }
  1285.  
  1286.     /* now unlink from spat list */
  1287.  
  1288.     for (entry = defstash->tbl_array['_']; entry; entry = entry->hent_next) {
  1289.     register HASH *stash;
  1290.     STAB *stab = (STAB*)entry->hent_val;
  1291.  
  1292.     if (!stab)
  1293.         continue;
  1294.     stash = stab_hash(stab);
  1295.     if (!stash || stash->tbl_spatroot == Null(SPAT*))
  1296.         continue;
  1297.     if (stash->tbl_spatroot == spat)
  1298.         stash->tbl_spatroot = spat->spat_next;
  1299.     else {
  1300.         for (sp = stash->tbl_spatroot;
  1301.           sp && sp->spat_next != spat;
  1302.           sp = sp->spat_next)
  1303.         /*SUPPRESS 530*/
  1304.         ;
  1305.         if (sp)
  1306.         sp->spat_next = spat->spat_next;
  1307.     }
  1308.     }
  1309.     Safefree(spat);
  1310. }
  1311.  
  1312. /* Recursively descend a command sequence and push the address of any string
  1313.  * that needs saving on recursion onto the tosave array.
  1314.  */
  1315.  
  1316. static int
  1317. cmd_tosave(cmd,willsave)
  1318. register CMD *cmd;
  1319. int willsave;                /* willsave passes down the tree */
  1320. {
  1321.     register CMD *head = cmd;
  1322.     int shouldsave = FALSE;        /* shouldsave passes up the tree */
  1323.     int tmpsave;
  1324.     register CMD *lastcmd = Nullcmd;
  1325.  
  1326.     while (cmd) {
  1327.     if (cmd->c_expr)
  1328.         shouldsave |= arg_tosave(cmd->c_expr,willsave);
  1329.     switch (cmd->c_type) {
  1330.     case C_WHILE:
  1331.         if (cmd->ucmd.ccmd.cc_true) {
  1332.         tmpsave = cmd_tosave(cmd->ucmd.ccmd.cc_true,willsave);
  1333.  
  1334.         /* Here we check to see if the temporary array generated for
  1335.          * a foreach needs to be localized because of recursion.
  1336.          */
  1337.         if (tmpsave && (cmd->c_flags & CF_OPTIMIZE) == CFT_ARRAY) {
  1338.             if (lastcmd &&
  1339.               lastcmd->c_type == C_EXPR &&
  1340.               lastcmd->c_expr) {
  1341.             ARG *arg = lastcmd->c_expr;
  1342.  
  1343.             if (arg->arg_type == O_ASSIGN &&
  1344.                 arg[1].arg_type == A_LEXPR &&
  1345.                 arg[1].arg_ptr.arg_arg->arg_type == O_LARRAY &&
  1346.                 strnEQ("_GEN_",
  1347.                   stab_name(
  1348.                 arg[1].arg_ptr.arg_arg[1].arg_ptr.arg_stab),
  1349.                   5)) {    /* array generated for foreach */
  1350.                 (void)localize(arg);
  1351.             }
  1352.             }
  1353.  
  1354.             /* in any event, save the iterator */
  1355.  
  1356.             (void)apush(tosave,cmd->c_short);
  1357.         }
  1358.         shouldsave |= tmpsave;
  1359.         }
  1360.         break;
  1361.     case C_BLOCK:
  1362.     case C_ELSE:
  1363.     case C_IF:
  1364.         if (cmd->ucmd.ccmd.cc_true)
  1365.         shouldsave |= cmd_tosave(cmd->ucmd.ccmd.cc_true,willsave);
  1366.         break;
  1367.     case C_EXPR:
  1368.         if (cmd->ucmd.acmd.ac_expr)
  1369.         shouldsave |= arg_tosave(cmd->ucmd.acmd.ac_expr,willsave);
  1370.         break;
  1371.     }
  1372.     lastcmd = cmd;
  1373.     cmd = cmd->c_next;
  1374.     if (cmd && cmd == head)        /* reached end of while loop */
  1375.         break;
  1376.     }
  1377.     return shouldsave;
  1378. }
  1379.  
  1380. static int
  1381. arg_tosave(arg,willsave)
  1382. register ARG *arg;
  1383. int willsave;
  1384. {
  1385.     register int i;
  1386.     int shouldsave = FALSE;
  1387.  
  1388.     for (i = arg->arg_len; i >= 1; i--) {
  1389.     switch (arg[i].arg_type & A_MASK) {
  1390.     case A_NULL:
  1391.         break;
  1392.     case A_LEXPR:
  1393.     case A_EXPR:
  1394.         shouldsave |= arg_tosave(arg[i].arg_ptr.arg_arg,shouldsave);
  1395.         break;
  1396.     case A_CMD:
  1397.         shouldsave |= cmd_tosave(arg[i].arg_ptr.arg_cmd,shouldsave);
  1398.         break;
  1399.     case A_WORD:
  1400.     case A_STAB:
  1401.     case A_LVAL:
  1402.     case A_READ:
  1403.     case A_GLOB:
  1404.     case A_ARYLEN:
  1405.     case A_SINGLE:
  1406.     case A_DOUBLE:
  1407.     case A_BACKTICK:
  1408.         break;
  1409.     case A_SPAT:
  1410.         shouldsave |= spat_tosave(arg[i].arg_ptr.arg_spat);
  1411.         break;
  1412.     }
  1413.     }
  1414.     switch (arg->arg_type) {
  1415.     case O_RETURN:
  1416.     saw_return = TRUE;
  1417.     break;
  1418.     case O_EVAL:
  1419.     case O_SUBR:
  1420.     shouldsave = TRUE;
  1421.     break;
  1422.     }
  1423.     if (willsave)
  1424.     (void)apush(tosave,arg->arg_ptr.arg_str);
  1425.     return shouldsave;
  1426. }
  1427.  
  1428. static int
  1429. spat_tosave(spat)
  1430. register SPAT *spat;
  1431. {
  1432.     int shouldsave = FALSE;
  1433.  
  1434.     if (spat->spat_runtime)
  1435.     shouldsave |= arg_tosave(spat->spat_runtime,FALSE);
  1436.     if (spat->spat_repl) {
  1437.     shouldsave |= arg_tosave(spat->spat_repl,FALSE);
  1438.     }
  1439.  
  1440.     return shouldsave;
  1441. }
  1442.  
  1443.